import 'dart:math';

import 'package:flutter/material.dart';

String _defaultText = "";

/// 获取文字信息
TextPainter getTextInfo(String text, TextStyle style,
    {int maxLines = 2 ^ 23,
      double width = double.infinity,
      String? ellipsis,
      textDirection = TextDirection.ltr}) {
  TextSpan span = TextSpan(text: text, style: style);
  return TextPainter(
    text: span,
    maxLines: maxLines,
    ellipsis: ellipsis,
    textDirection: textDirection,
  )..layout(maxWidth: width);
}


class Marquee extends StatefulWidget {
  //滚动文字
  final String? content;

  //纵向滚动的文字组
  final List<String>? contentList;

  //滚动方向
  final Axis scrollDirection;

  //滚动总时长
  final Duration duration;

  //文字样式
  final TextStyle textStyle;

  //是否允许滚动
  final bool enableScroll;

  //不满全屏时是否强制滚动 仅用在横向
  final bool forceScroll;

  // 滚动效果 仅用在不自动滑动时
  final ScrollPhysics? physics;

  //仅用在自定义文字组 纵向滑动时
  final TextOverflow overflow;

  //仅用在纵向滑动时文字对齐方式
  final TextAlign textAlign;

  const Marquee({
    Key? key,
    this.content,
    this.contentList,
    this.scrollDirection = Axis.horizontal,
    this.duration = const Duration(milliseconds: 10000),
    this.textStyle = const TextStyle(color: Colors.black, fontSize: 16),
    this.enableScroll = true,
    this.forceScroll = false,
    this.physics,
    this.overflow = TextOverflow.ellipsis,
    this.textAlign = TextAlign.start,
  }) : super(key: key);

  @override
  State<Marquee> createState() => _MarqueeState();
}

class _MarqueeState extends State<Marquee>
    with SingleTickerProviderStateMixin {
  //获取组件最大宽度与高度
  Size _viewSize = const Size(0, 0);

  //动画的控制器
  late AnimationController _animationController;

  //动画
  late Animation<Offset> _animation;

  //滚动控制器
  final ScrollController _scrollController = ScrollController();

  @override
  void initState() {
    super.initState();

    _animationController =
        AnimationController(vsync: this, duration: widget.duration);
    _animation = Tween(begin: const Offset(0, 0), end: const Offset(1, 0))
        .animate(_animationController);
    _animation.addListener(() {
      //如果有子组件
      if (_scrollController.hasClients) {
        if (_scrollController.position.hasContentDimensions) {
          if (widget.scrollDirection == Axis.horizontal) {
            //前后两端内容+空白区域
            double fullLength = _scrollController.position.maxScrollExtent +
                2 * _viewSize.width;
            _scrollController
                .jumpTo(_animation.value.dx * fullLength - _viewSize.width);
          } else {
            _scrollController.jumpTo(_animation.value.dx *
                _scrollController.position.maxScrollExtent);
          }
        }
      }
    });
  }

  @override
  void dispose() {
    _scrollController.dispose();
    _animationController.dispose();
    super.dispose();
  }

  @override
  void didUpdateWidget(covariant Marquee oldWidget) {
    // TODO: implement didUpdateWidget
    super.didUpdateWidget(oldWidget);
    if (oldWidget != widget) {
      _animationController.duration = widget.duration;
    }
  }

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, size) {
      _viewSize = Size(size.maxWidth, size.maxHeight);
      String content = widget.content ?? _defaultText;
      List<String> contentList = widget.contentList ?? [];
      Widget child = Container();
      if (widget.scrollDirection == Axis.horizontal) {
        child = _buildHorizontalView(contentList, content, size);
      } else {
        child = _buildVerticalView(contentList, content, size);
      }
      return child;
    });
  }

  //构建纵向列表
  Widget _buildVerticalView(
      List<String> contentList, String content, BoxConstraints size) {
    if (widget.contentList != null && widget.contentList!.isNotEmpty) {
      contentList = widget.contentList!;
    } else {
      contentList = [];
      while (content.isNotEmpty) {
        TextPainter painter = getTextInfo(content, widget.textStyle,
            maxLines: 1, width: _viewSize.width);
        int maxIndex =
            painter.getPositionForOffset(Offset(_viewSize.width, 0)).offset;
        contentList.add(content.substring(0, min((maxIndex), content.length)));
        content = content.substring(min(maxIndex, content.length));
      }
    }
    TextPainter painter = getTextInfo(_defaultText, widget.textStyle);
    //如果行数大于一滚动
    if (contentList.length > 1 && widget.enableScroll) {
      _animationController.repeat();
    } else {
      _animationController.stop();
    }
    return ConstrainedBox(
      constraints: BoxConstraints(
          minWidth: _viewSize.width,
          minHeight: painter.height,
          maxHeight: painter.height),
      child: ListView.builder(
          physics: widget.physics,
          itemBuilder: (context, index) => Text(
            contentList[index],
            textAlign: widget.textAlign,
            style: widget.textStyle,
            maxLines: 1,
            overflow: widget.overflow,
          ),
          shrinkWrap: true,
          controller: _scrollController,
          itemCount: contentList.length,
          scrollDirection: Axis.vertical),
    );
  }

  //构建横向滚动组件
  SingleChildScrollView _buildHorizontalView(
      List<String> contentList, String content, BoxConstraints size) {
    if (widget.content != null) {
      content = widget.content!;
    } else if (widget.contentList != null) {
      content = contentList.join("");
    }

    TextPainter painter = getTextInfo(content, widget.textStyle,
        width: _viewSize.width, maxLines: 1);
    if (widget.enableScroll &&
        (!painter.didExceedMaxLines && widget.forceScroll ||
            painter.didExceedMaxLines)) {
      _animationController.repeat();
    } else {
      _animationController.stop();
    }
    return SingleChildScrollView(
      controller: _scrollController,
      scrollDirection: Axis.horizontal,
      child: ConstrainedBox(
          constraints: BoxConstraints(minWidth: _viewSize.width),
          child: Text(
            content,
            style: widget.textStyle,
          )),
    );
  }
}